package com.hanlp.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 东方财富股票数据爬取工具类
 * 提供股票行情、K线、基本信息等数据获取功能
 */
public class EastMoneyStockUtil {

    // 基础URL常量
    private static final String BASE_URL = "http://push2.eastmoney.com";
    private static final String HISTORY_URL = "http://push2his.eastmoney.com";
    private static final String DATACENTER_URL = "http://datacenter-web.eastmoney.com";

    // 默认token
    private static final String DEFAULT_UT = "bd1d9ddb04089700cf9c27f6f7426281";
    private static final String KLINE_UT = "fa5fd1943c7b386f172d6893dbfba10b";

    // 默认字段
    private static final String STOCK_FIELDS = "f43,f44,f45,f46,f60,f47,f48,f169,f170,f57,f58";
    private static final String LIST_FIELDS = "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152";
    private static final String KLINE_FIELDS1 = "f1,f2,f3,f4,f5";
    private static final String KLINE_FIELDS2 = "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61";

    /**
     * 获取股票实时行情数据
     *
     * @param secid 股票代码，格式：市场代码.股票代码（如：0.000001）
     * @return JSON格式的行情数据
     * @throws IOException 网络请求异常
     */
    public static String getStockRealTimeData(String secid) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("fields", STOCK_FIELDS);

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/stock/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取股票实时行情数据Bean对象
     * @param secid 股票代码（格式：市场.代码，如"0.000001"）
     * @return StockRealTimeData对象
     * @throws IOException 网络请求异常
     */
    /*
    public static StockRealTimeData getStockRealTimeDataBean(String secid) throws IOException {
        String jsonResponse = getStockRealTimeData(secid);
        return JsonUtil.parseStockRealTimeData(jsonResponse);
    }
    */

    /**
     * 获取股票实时行情数据（自定义字段）
     *
     * @param secid  股票代码
     * @param fields 自定义字段，用逗号分隔
     * @return JSON格式的行情数据
     * @throws IOException 网络请求异常
     */
    public static String getStockRealTimeData(String secid, String fields) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("fields", fields);

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/stock/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取股票列表
     *
     * @param pageNum   页码（从1开始）
     * @param pageSize  每页数量
     * @param sortField 排序字段（如：f3表示涨跌幅）
     * @param sortOrder 排序方式（1为正序，0为倒序）
     * @return JSON格式的股票列表数据
     * @throws IOException 网络请求异常
     */
    public static String getStockList(int pageNum, int pageSize, String sortField, int sortOrder) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("pn", String.valueOf(pageNum));
        params.put("pz", String.valueOf(pageSize));
        params.put("po", String.valueOf(sortOrder));
        params.put("np", "1");
        params.put("ut", DEFAULT_UT);
        params.put("fltt", "2");
        params.put("invt", "2");
        params.put("fid", sortField);
        params.put("fs", "m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23"); // 沪深A股
        params.put("fields", LIST_FIELDS);

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/ulist/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取大盘指数数据Bean对象
     * @param indexCodes 指数代码数组
     * @return ApiResponse<List < IndexData>>对象
     * @throws IOException 网络请求异常
     */
    /*
    public static ApiResponse<List<IndexData>> getIndexDataBean(String[] indexCodes) throws IOException {
        String jsonResponse = getIndexData(indexCodes);
        return JsonUtil.parseIndexData(jsonResponse);
    }
    */

    /**
     * 获取股票列表Bean对象
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页数量
     * @param sortField 排序字段（如：f3表示涨跌幅）
     * @param sortOrder 排序方式（1为正序，0为倒序）
     * @return ApiResponse<List < StockRealTimeData>>对象
     * @throws IOException 网络请求异常
     */
    /*
    public static ApiResponse<List<StockRealTimeData>> getStockListBean(int pageNum, int pageSize, String sortField, int sortOrder) throws IOException {
        String jsonResponse = getStockList(pageNum, pageSize, sortField, sortOrder);
        return JsonUtil.parseStockList(jsonResponse);
    }
    */

    /**
     * 获取股票K线数据
     *
     * @param secid      股票代码
     * @param klineType  K线类型（1:1分钟, 5:5分钟, 15:15分钟, 30:30分钟, 60:60分钟, 101:日K, 102:周K, 103:月K）
     * @param adjustType 复权类型（0:不复权, 1:前复权, 2:后复权）
     * @param startDate  开始日期（格式：20220101）
     * @param endDate    结束日期（格式：20221231）
     * @return JSON格式的K线数据
     * @throws IOException 网络请求异常
     */
    public static String getKLineData(String secid, int klineType, int adjustType,
                                      String startDate, String endDate) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("ut", KLINE_UT);
        params.put("fields1", KLINE_FIELDS1);
        params.put("fields2", KLINE_FIELDS2);
        params.put("klt", String.valueOf(klineType));
        params.put("fqt", String.valueOf(adjustType));
        params.put("beg", startDate);
        params.put("end", endDate);

        String url = HttpUtil.buildUrl(HISTORY_URL + "/api/qt/stock/kline/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取股票K线数据Bean对象
     * @param secid 股票代码
     * @param klineType K线类型（1:1分钟, 5:5分钟, 15:15分钟, 30:30分钟, 60:60分钟, 101:日K, 102:周K, 103:月K）
     * @param adjustType 复权类型（0:不复权, 1:前复权, 2:后复权）
     * @param startDate 开始日期（格式：20220101）
     * @param endDate 结束日期（格式：20221231）
     * @return KLineData对象
     * @throws IOException 网络请求异常
     */
    /*
    public static KLineData getKLineDataBean(String secid, int klineType, int adjustType, 
                                           String startDate, String endDate) throws IOException {
        String jsonResponse = getKLineData(secid, klineType, adjustType, startDate, endDate);
        return JsonUtil.parseKLineData(jsonResponse);
    }
    */

    /**
     * 获取股票基本信息
     *
     * @param secid 股票代码
     * @return JSON格式的股票基本信息
     * @throws IOException 网络请求异常
     */
    public static String getStockDetails(String secid) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("ut", DEFAULT_UT);
        params.put("fields", "f57,f58,f162,f163,f164,f165,f166,f167,f168");

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/stock/details/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取股票资金流向数据
     *
     * @param secid 股票代码
     * @return JSON格式的资金流向数据
     * @throws IOException 网络请求异常
     */
    public static String getStockFundFlow(String secid) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("ut", DEFAULT_UT);
        params.put("fields1", "f1,f2,f3,f7");
        params.put("fields2", "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65");

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/stock/fflow/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取指数数据
     *
     * @param indexCodes 指数代码，多个用逗号分隔
     * @return JSON格式的指数数据
     * @throws IOException 网络请求异常
     */
    public static String getIndexData(String indexCodes) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("fltt", "2");
        params.put("secids", indexCodes);
        params.put("fields", "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152");

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/ulist.np/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取板块数据
     *
     * @param blockType 板块类型（industry:行业板块, concept:概念板块, region:地域板块）
     * @param pageNum   页码
     * @param pageSize  每页数量
     * @return JSON格式的板块数据
     * @throws IOException 网络请求异常
     */
    public static String getBlockData(String blockType, int pageNum, int pageSize) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("pn", String.valueOf(pageNum));
        params.put("pz", String.valueOf(pageSize));
        params.put("po", "1");
        params.put("np", "1");
        params.put("ut", DEFAULT_UT);
        params.put("fltt", "2");
        params.put("invt", "2");
        params.put("fid", "f3");

        // 根据板块类型设置筛选条件
        switch (blockType.toLowerCase()) {
            case "industry":
                params.put("fs", "m:90+t:2");
                break;
            case "concept":
                params.put("fs", "m:90+t:3");
                break;
            case "region":
                params.put("fs", "m:90+t:1");
                break;
            default:
                throw new IllegalArgumentException("不支持的板块类型: " + blockType);
        }

        params.put("fields", LIST_FIELDS);

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/clist/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取财务报表数据
     *
     * @param reportName 报表名称
     * @param columns    字段列表
     * @param filter     过滤条件
     * @param pageNum    页码
     * @param pageSize   每页数量
     * @return JSON格式的财务数据
     * @throws IOException 网络请求异常
     */
    public static String getFinancialData(String reportName, String columns, String filter,
                                          int pageNum, int pageSize) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("reportName", reportName);
        params.put("columns", columns);
        if (filter != null && !filter.isEmpty()) {
            params.put("filter", filter);
        }
        params.put("pageNumber", String.valueOf(pageNum));
        params.put("pageSize", String.valueOf(pageSize));

        String url = HttpUtil.buildUrl(DATACENTER_URL + "/api/data/v1/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 批量获取股票实时行情（控制请求频率）
     *
     * @param secids  股票代码数组
     * @param delayMs 每次请求间隔毫秒数
     * @return 股票行情数据数组
     */
    public static String[] batchGetStockData(String[] secids, long delayMs) {
        String[] results = new String[secids.length];

        for (int i = 0; i < secids.length; i++) {
            try {
                results[i] = getStockRealTimeData(secids[i]);

                // 控制请求频率，避免被限制
                if (i < secids.length - 1 && delayMs > 0) {
                    HttpUtil.sleep(delayMs);
                }
            } catch (IOException e) {
                results[i] = "{\"error\":\"" + e.getMessage() + "\"}";
            }
        }

        return results;
    }
}